package com.yanqu.road.server.manager.activity.flowerstudy;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.flowerstudy.config.FlowerStudyConfig;
import com.yanqu.road.entity.activity.flowerstudy.config.FlowerStudyExamConfig;
import com.yanqu.road.entity.activity.flowerstudy.config.FlowerStudyExamQuestionConfig;
import com.yanqu.road.entity.activity.flowerstudy.config.FlowerStudySessionRewardConfig;
import com.yanqu.road.entity.activity.flowerstudy.data.cross.*;

import com.yanqu.road.entity.enums.activity.flowerstudy.eFlowerStudyPeriodType;
import com.yanqu.road.entity.enums.activity.flowerstudy.eFlowerStudyRoomDataSyncType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eSexType;
import com.yanqu.road.entity.language.LanguageType;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.bussiness.activity.FlowerStudyBusiness;
import com.yanqu.road.logic.cross.CrossActivityRankListModel;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.activity.FlowerStudyProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityRankMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.manger.NameMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class CrossFlowerStudyActivity {

    private static Logger logger = LogManager.getLogger(CrossFlowerStudyActivity.class.getName());

    private static int AiMaxId = 10000;

    private ActivityInfo activityInfo;

    private List<String> languageList = new ArrayList<>();

    //-------------阶段数据
    Map<Integer, CrossFlowerStudyExamSessionData> sessionDataMap = new ConcurrentHashMap<>();
    //-------------所有玩家的数据 入库的那种
    Map<Long, CrossFlowerStudyUserExamData> userExamDataMap = new ConcurrentHashMap<>();

    //-------------等待中的房间
    Map<String, CrossFlowerStudyExamRoomData> waitingRoomDataMap = new ConcurrentHashMap<>();
    //-------------游戏中的房间
    Map<String, CrossFlowerStudyExamRoomData> gamingRoomDataMap = new ConcurrentHashMap<>();
    //-------------已经结束的房间
    Map<String, CrossFlowerStudyExamRoomData> endRoomDataMap = new ConcurrentHashMap<>();

    //-------------npc的数据
    Map<Long, CrossFlowerStudyExamNpcData> npcDataMap = new ConcurrentHashMap<>();

    Random random = new Random();

    public static Object lock = new Object();

    public void save(){
        for (CrossFlowerStudyExamSessionData sessionData:sessionDataMap.values()){
            if (sessionData.isInsertOption()){
                FlowerStudyBusiness.addCrossFlowerStudyExamSessionData(sessionData);
            }else if (sessionData.isUpdateOption()){
                FlowerStudyBusiness.updateCrossFlowerStudyExamSessionData(sessionData);
            }
        }
        for (CrossFlowerStudyUserExamData userExamData:userExamDataMap.values()){
            if (userExamData.isInsertOption()){
                FlowerStudyBusiness.addFlowerStudyCrossExamUserData(userExamData);
            }else if (userExamData.isUpdateOption()){
                FlowerStudyBusiness.updateFlowerStudyCrossExamUserData(userExamData);
            }
        }
        for (CrossFlowerStudyExamRoomData roomData:waitingRoomDataMap.values()){
            if (roomData.isInsertOption()){
                FlowerStudyBusiness.addCrossFlowerStudyExamRoomData(roomData);
            }else if (roomData.isUpdateOption()){
                FlowerStudyBusiness.updateCrossFlowerStudyExamRoomData(roomData);
            }
        }
        for (CrossFlowerStudyExamRoomData roomData:gamingRoomDataMap.values()){
            if (roomData.isInsertOption()){
                FlowerStudyBusiness.addCrossFlowerStudyExamRoomData(roomData);
            }else if (roomData.isUpdateOption()){
                FlowerStudyBusiness.updateCrossFlowerStudyExamRoomData(roomData);
            }
        }
        for (CrossFlowerStudyExamRoomData roomData:endRoomDataMap.values()){
            if (roomData.isInsertOption()){
                FlowerStudyBusiness.addCrossFlowerStudyExamRoomData(roomData);
            }else if (roomData.isUpdateOption()){
                FlowerStudyBusiness.updateCrossFlowerStudyExamRoomData(roomData);
            }
        }
    }

    public void init(){
        userExamDataMap = FlowerStudyBusiness.getCrossFlowerStudyUserExamData(activityInfo.getActivityId());
        sessionDataMap = FlowerStudyBusiness.getCrossFlowerStudyExamSessionDataMap(activityInfo.getActivityId());

        waitingRoomDataMap = FlowerStudyBusiness.getCrossFlowerStudyExamRoomDataMap(activityInfo.getActivityId(),0);
        gamingRoomDataMap = FlowerStudyBusiness.getCrossFlowerStudyExamRoomDataMap(activityInfo.getActivityId(),1);
        endRoomDataMap = FlowerStudyBusiness.getCrossFlowerStudyExamRoomDataMap(activityInfo.getActivityId(),2);


        if (sessionDataMap == null|| sessionDataMap.isEmpty()){
            FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
            if (config == null){
                logger.error("flowerStudy config is null activityId:{}",activityInfo.getActivityId());
                return;
            }
            for (FlowerStudyExamConfig examConfig:config.getExamConfigMap().values()){
                CrossFlowerStudyExamSessionData sessionData = new CrossFlowerStudyExamSessionData();
                sessionData.setActivityId(activityInfo.getActivityId());
                sessionData.setSessionId(examConfig.getId());
                sessionData.setRoomId(0);
                sessionData.setRoomType(examConfig.getType());
                sessionData.setState(0);
                sessionData.setAtomicRoomId(new AtomicInteger(sessionData.getRoomId()+1));
                sessionData.setInsertOption();
                sessionDataMap.putIfAbsent(sessionData.getSessionId(),sessionData);
            }
        }
    }

    /**
     * 检测结算
     */
    public void checkSessionChange(){
        FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
        if (config == null){
            logger.error("flowerStudy config is null activityId:{}",activityInfo.getActivityId());
            return;
        }
        if (sessionDataMap == null|| sessionDataMap.isEmpty()){
            for (FlowerStudyExamConfig examConfig:config.getExamConfigMap().values()){
                CrossFlowerStudyExamSessionData sessionData = new CrossFlowerStudyExamSessionData();
                sessionData.setActivityId(activityInfo.getActivityId());
                sessionData.setSessionId(examConfig.getId());
                sessionData.setRoomId(0);
                sessionData.setRoomType(examConfig.getType());
                sessionData.setState(0);
                sessionData.setAtomicRoomId(new AtomicInteger(sessionData.getRoomId()+1));
                sessionData.setInsertOption();
                sessionDataMap.putIfAbsent(sessionData.getSessionId(),sessionData);
            }
        }

        for (CrossFlowerStudyExamSessionData sessionData:sessionDataMap.values()){
            if (sessionData.getState() == 3){
                continue;
            }
            int sessionId = sessionData.getSessionId();
            FlowerStudyExamConfig examConfig = config.getExamConfigMap().get(sessionId);
            if (examConfig != null){

                Date date = new Date();
                //开始
                if (date.after(examConfig.getStartDate())&&date.before(examConfig.getEndDate())){
                    if (sessionData.getState() != 1){
                        logger.info("flowerStudy session start activityId {},sessionId:{}",activityInfo.getActivityId(),sessionId);
                        sessionData.setState(1);
                        sessionData.setUpdateOption();
                    }
                }
                //未开始
                if (date.before(examConfig.getStartDate())){
                    if (sessionData.getState() != 0){
                        logger.info("flowerStudy session change to noOpen activityId {},sessionId:{}",activityInfo.getActivityId(),sessionId);
                        sessionData.setState(0);
                        sessionData.setUpdateOption();
                    }
                }

                //结束
                if (date.after(examConfig.getEndDate())){
                    if (sessionData.getState() != 2){
                        logger.info("flowerStudy session change to end activityId {},sessionId:{}",activityInfo.getActivityId(),sessionId);
                        sessionData.setState(2);
                        sessionData.setUpdateOption();
                    }
                }
            }
        }

    }

    /**
     * 获取当前进行中的考试场次
     */
    public int getNowOpenTest() {
        FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
        if (config == null){
            return 0;
        }
        int examNowPeriod = config.getExamNowPeriod();
        if (examNowPeriod == eFlowerStudyPeriodType.noOpenLocal.getValue()
                ||examNowPeriod == eFlowerStudyPeriodType.localToProvincial.getValue()
                ||examNowPeriod == eFlowerStudyPeriodType.provincialToPalace.getValue()
                ||examNowPeriod == eFlowerStudyPeriodType.allEnd.getValue()){
            return 0;
        }
        int nowStatus = config.getExamStatus();
        if (nowStatus == 0){
            return 0;
        }
        CrossFlowerStudyExamSessionData sessionData = sessionDataMap.get(nowStatus);
        if (sessionData == null){
            return 0;
        }
        if (sessionData.getState() != 1){
            return 0;
        }

        return sessionData.getSessionId();
    }


    /**
     * 检测游玩的房间是否需要切换题目和结算
     */

    public void checkGamingRoom(){
        for (CrossFlowerStudyExamRoomData roomData:gamingRoomDataMap.values()){
            FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
            if (config == null){
                return;
            }
            int answerTime = config.getAnswerTime();
            int determineTime = config.getDetermineTime();
            if (roomData.getRoomState() == 0){
                CrossFlowerStudyExamRoomData remove = gamingRoomDataMap.remove(roomData.getRoomId());
                waitingRoomDataMap.putIfAbsent(remove.getRoomId(),remove);
                continue;
            }
            if (roomData.getRoomState() == 2){
                CrossFlowerStudyExamRoomData remove = gamingRoomDataMap.remove(roomData.getRoomId());
                endRoomDataMap.putIfAbsent(remove.getRoomId(),remove);
                continue;
            }
            if (roomData.getRoomState() != 1 ){
                logger.error("flowerStudy room state error activityId:{} roomId:{}",activityInfo.getActivityId(),roomData.getRoomId());
            }
            long now = System.currentTimeMillis();
            synchronized (roomData){
                int oneQuestionScore = CrossFlowerStudyConfigMgr.getOneQuestionScore(activityInfo.getActivityId());
                boolean allQuestionOver = roomData.getNowQuestionIndex() + 1 >= roomData.getQuestionList().size();
                if (roomData.getThisQuestionStartTime() + answerTime* 1000L <= now){    //6.4.1热更代码 determineTime* 1000L 被删除了 挪到后面做表现用
                    List<CrossFlowerStudyUserExamData> needRemoveList = new ArrayList<>();
                    for (CrossFlowerStudyUserBattleData battleData:roomData.getUserBattleDataMap().values()){
                        //淘汰的不管了
                        if (battleData.getNowState() == 3){
                            continue;
                        }

                        //自由人计时
                        if (battleData.getNowState() == 1){
                            battleData.setTotalTimeThisExam(battleData.getTotalTimeThisExam()+answerTime);
                        }else if (battleData.getNowState() == 2){   //提前交卷人
                            battleData.setNowState(1);          //解锁咯
                        }
                        //本题的选项推到下一题
                        List<Integer> nowChooseList = battleData.getNowChooseList();
                        int nowChoose = nowChooseList.get(roomData.getNowQuestionIndex());
                        if (!allQuestionOver){
                            if (nowChooseList.size() > roomData.getNowQuestionIndex()+1){
                                nowChooseList.set(roomData.getNowQuestionIndex()+1,nowChoose);
                            }
                        }

                        //检测本题目是否正确
                        boolean chooseRight = checkChooseRight(roomData.getQuestionList().get(roomData.getNowQuestionIndex()), nowChoose);
                        //错了 或者掉线了
                        if (!chooseRight || battleData.getNowState() == 0){
                            battleData.setNowState(3);  //死翘翘了
                            if (battleData.getUserId() <AiMaxId){
                                continue;
                            }
                            CrossFlowerStudyUserExamData userExamData = userExamDataMap.get(battleData.getUserId());
                            if (userExamData == null){
                                logger.info("花生书房 活动id{},玩家信息不存在 userId:{},房间id:{}",activityInfo.getActivityId(),battleData.getUserId(),roomData.getRoomId());
                                continue;
                            }
                            //结算
                            dealGameOver(battleData,roomData);
                            needRemoveList.add(userExamData);


                        }else {     //对了 留下
                            battleData.setScoreThisExam(battleData.getScoreThisExam()+oneQuestionScore);
                        }
                    }
                    for (CrossFlowerStudyUserExamData userExamData:needRemoveList){
                        syncRoomEndEventToOneUser(userExamData.getUserId(),userExamData.getServerId(),eFlowerStudyRoomDataSyncType.playerEliminate.getValue(),roomData);
                    }


                    //如果最后一题 活着没活人了  房间结算
                    boolean hasRealPlayer = checkHasRealPlayer(roomData);
                    if (allQuestionOver || !hasRealPlayer){
                        roomData.setNowQuestionIndex(roomData.getNowQuestionIndex()+1);
                        roomData.setRoomState(2);
                        //结算
                        for (CrossFlowerStudyUserBattleData battleData:roomData.getUserBattleDataMap().values()){
                            //所有活着的人
                            if (battleData.getNowState() == 0){     //掉了 应该不会有 不管了
                                continue;
                            }
                            if (battleData.getNowState() == 3) {
                                continue;
                            }

                            long userId = battleData.getUserId();
                            if (userId <= AiMaxId){    //假人
                                continue;
                            }
                            CrossFlowerStudyUserExamData userData = getUserData(userId);
                            if (userData == null){
                                continue;
                            }
                            dealGameOver(battleData,roomData);
                            syncRoomEndEventToOneUser(userData.getUserId(),userData.getServerId(),eFlowerStudyRoomDataSyncType.gameEnd.getValue(),roomData);
                        }
                        //二次清除
//                        clearEndRoom(roomData);
                        CrossFlowerStudyExamRoomData remove = gamingRoomDataMap.remove(roomData.getRoomId());
                        if (remove != null){
                            endRoomDataMap.putIfAbsent(remove.getRoomId(),remove);
                        }
                    }else {
                        //其他的下一题
                        roomData.setNowQuestionIndex(roomData.getNowQuestionIndex()+1);
                        roomData.setThisQuestionStartTime(roomData.getThisQuestionStartTime() + answerTime * 1000L + determineTime* 1000L);

                        syncRoomEventToRoomUser(eFlowerStudyRoomDataSyncType.gameNextQuestion.getValue(),roomData);
                    }
                } else if (roomData.getThisQuestionStartTime() + (answerTime + 1) * 1000L > now){
                    //ai动一下
                    aiRandomMove(roomData);

                }
            }

        }

    }

    /**
     * 检测是否房间还有玩家
     */
    public boolean checkHasRealPlayer(CrossFlowerStudyExamRoomData roomData){
        for (CrossFlowerStudyUserBattleData battleData:roomData.getUserBattleDataMap().values()){
            if (battleData.getUserId() > AiMaxId && battleData.getNowState() != 3){
                return true;
            }
        }
        return false;
    }

    /**
     * 结算
     */
    public void dealGameOver(CrossFlowerStudyUserBattleData battleData,CrossFlowerStudyExamRoomData roomData){
        if (battleData.getUserId()<=AiMaxId){
            return;
        }

        CrossFlowerStudyUserExamData userExamData = userExamDataMap.get(battleData.getUserId());
        if (userExamData == null){
            logger.info("花生书房 活动id{},玩家信息不存在 userId:{},房间id:{}",activityInfo.getActivityId(),battleData.getUserId(),roomData.getRoomId());
            return;
        }
        int rightNum = roomData.getNowQuestionIndex();      //从0开始 所以这里是第几就对了几题
        FlowerStudySessionRewardConfig flowerStudySessionRewardConfig = null;
        for (int i = rightNum;i >=0;i--){
            flowerStudySessionRewardConfig = CrossFlowerStudyConfigMgr.getFlowerStudySessionRewardConfig(activityInfo.getActivityId(), roomData.getRoomType(), i);
            if (flowerStudySessionRewardConfig != null){
                break;
            }
        }
        if (flowerStudySessionRewardConfig != null){
            Property reward = PropertyHelper.parseStringToProperty(flowerStudySessionRewardConfig.getReward());
            battleData.setReward(PropertyHelper.parsePropertyToString(reward));
        }
        synchronized (userExamData){
            //清除房间信息
            userExamData.setNowRoomId("");
            //加分 加时间
            addScore(userExamData,roomData.getRoomType(),battleData.getScoreThisExam(),battleData.getTotalTimeThisExam());
        }

    }

    /**
     * 加分
     */
    public void addScore(CrossFlowerStudyUserExamData userExamData,int roomType,long score,long time){
        if (userExamData == null){
            return;
        }
        if (roomType == 1){
            if (!checkCanGetScore(1)){
                logger.info("花生书房 活动id{},所有乡试过期 不能更新玩家积分 userId:{},房间id:{}",activityInfo.getActivityId(),userExamData.getUserId(),userExamData.getNowRoomId());
                return;
            }

            userExamData.setLocalExamScore(userExamData.getLocalExamScore()+score);
            userExamData.setLocalExamTime(userExamData.getLocalExamTime()+time);
            //同步排行榜
            syncRankToGame(userExamData);
            return;
        }
        if (roomType == 2){
            if (!checkCanGetScore(2)){
                logger.info("花生书房 活动id{},所有省试过期 不能更新玩家积分 userId:{},房间id:{}",activityInfo.getActivityId(),userExamData.getUserId(),userExamData.getNowRoomId());
                return;
            }
            userExamData.setProvinceExamScore(userExamData.getProvinceExamScore()+score);
            userExamData.setProvinceExamTime(userExamData.getProvinceExamTime()+time);
            //同步排行榜
            syncRankToGame(userExamData);
            return;
        }
        if (roomType == 3){
            if (!checkCanGetScore(3)){
                logger.info("花生书房 活动id{},所有殿试过期 不能更新玩家积分 userId:{},房间id:{}",activityInfo.getActivityId(),userExamData.getUserId(),userExamData.getNowRoomId());
                return;
            }
            userExamData.setPalaceExamScore(userExamData.getPalaceExamScore()+score);
            userExamData.setPalaceExamTime(userExamData.getPalaceExamTime()+time);
            //同步排行榜
            syncRankToGame(userExamData);
            return;
        }

    }

    public boolean checkCanGetScore(int type){
        Date date = new Date();
        FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
        if (config == null){
            logger.error("花城书房活动id{}配置不存在",activityInfo.getActivityId());
            return false;
        }
        if (date.before(config.getExamBeginDate()) || date.after(config.getExamEndDate())){
            return false;
        }

        if (type == 1){
            if (date.before(config.getLocalExamBeginDate()) || date.after(config.getLocalExamEndDate())){
                return false;
            }
            return true;
        }else if (type == 2){
            if (date.before(config.getProvincialExamBeginDate()) || date.after(config.getProvincialExamEndDate())){
                return false;
            }
            return true;
        }else if (type == 3){
            if (date.before(config.getPalaceExamBeginDate()) || date.after(config.getPalaceExamEndDate())){
                return false;
            }
            return true;
        }
        return false;

    }


    /**
     * 检测选择是否正确
     */
    public boolean checkChooseRight(int questionId,int choose){
        FlowerStudyExamQuestionConfig questionConfig = CrossFlowerStudyConfigMgr.getExamQuestionConfig(activityInfo.getActivityId(), questionId);
        if (questionConfig == null){
            logger.error("花城书房活动id{}答题答案id{}配置不存在",activityInfo.getActivityId(),questionId);
            return true;
        }
        if (questionConfig.getAnswer() == choose){
            return true;
        }else {
            return false;
        }
    }


    /**
     * Ai瞎动一下
     */
    public void aiRandomMove(CrossFlowerStudyExamRoomData roomData){
        FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
        if (config == null){
            return;
        }
        //ai移动时间 一秒内不要乱动
        long aiLastMoveTime = roomData.getAiLastMoveTime();
        long now = System.currentTimeMillis();
        if (now - aiLastMoveTime < DateHelper.SECOND_MILLIONS){
            return;
        }
        //几率
        int moveRate = config.getAiAccuracy();
        int commitRate = config.getSitDownRate();

        int answerTime = config.getAnswerTime();

        Map<Long, CrossFlowerStudyUserBattleData> battleDataMap = roomData.getUserBattleDataMap();
        for (CrossFlowerStudyUserBattleData crossFlowerStudyUserBattleData:battleDataMap.values()){
            long aiId = crossFlowerStudyUserBattleData.getUserId();
            if (aiId <=AiMaxId){       //电脑人
                if (crossFlowerStudyUserBattleData.getNowState() != 1){     //锁定的不动
                    continue;
                }
                int randomNum = random.nextInt(1000);
                if (randomNum < commitRate && roomData.getThisQuestionStartTime() + answerTime* 1000L - 5 * 1000L <= now){      //最后几秒 判断提交
                    crossFlowerStudyUserBattleData.setNowState(2);
                    crossFlowerStudyUserBattleData.setTotalTimeThisExam(crossFlowerStudyUserBattleData.getScoreThisExam()+ (now - roomData.getThisQuestionStartTime())/1000);
                    syncChooseDataToRoomUser(aiId,crossFlowerStudyUserBattleData,roomData);
                    continue;
                }

                if (randomNum < moveRate){      //动
                    List<Integer> nowChooseList = crossFlowerStudyUserBattleData.getNowChooseList();
                    int oldNum = nowChooseList.get(roomData.getNowQuestionIndex());
                    if (oldNum == 1){
                        nowChooseList.set(roomData.getNowQuestionIndex(),2);
                    }else {
                        nowChooseList.set(roomData.getNowQuestionIndex(),1);
                    }
                    syncChooseDataToRoomUser(aiId,crossFlowerStudyUserBattleData,roomData);
                }
            }
        }
        roomData.setAiLastMoveTime(now);
    }

    /**
     * 玩家结束清出房间
     */
    private void clearEndRoom(CrossFlowerStudyExamRoomData roomData){
        Map<Long, CrossFlowerStudyUserBattleData> userBattleDataMap = roomData.getUserBattleDataMap();
        for (CrossFlowerStudyUserBattleData battleData:userBattleDataMap.values()){
            CrossFlowerStudyUserExamData userData = getUserData(battleData.getUserId());
            if (userData == null){
                continue;
            }

        }
    }


    /**
     * 检测未开始的房间是否可以开
     */
    public void checkWaitRoom(){
        FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
        if (config == null){
            return;
        }
        int examRoomPlayerNum = config.getExamRoomPlayerNum();

        for (CrossFlowerStudyExamRoomData roomData:waitingRoomDataMap.values()){
            synchronized (roomData){
            if (roomData.getRoomState() == 1){
                CrossFlowerStudyExamRoomData remove = waitingRoomDataMap.remove(roomData.getRoomId());
                gamingRoomDataMap.putIfAbsent(remove.getRoomId(),remove);
                continue;
            }else if (roomData.getRoomState() == 2){
                CrossFlowerStudyExamRoomData remove = waitingRoomDataMap.remove(roomData.getRoomId());
                endRoomDataMap.putIfAbsent(remove.getRoomId(),remove);
                continue;
            }
            if (roomData.getRoomState() != 0 ){
                logger.error("flowerStudy room state error activityId:{} roomId:{}",activityInfo.getActivityId(),roomData.getRoomId());
            }
            long now = System.currentTimeMillis();
                if (now > roomData.getMatchEndTime() || roomData.getUserBattleDataMap().size() >= examRoomPlayerNum){
                    addAiToMax(roomData);
                    roomData.setRoomState(1);
                    roomData.setNowQuestionIndex(0);
                    CrossFlowerStudyExamRoomData remove = waitingRoomDataMap.remove(roomData.getRoomId());
                    gamingRoomDataMap.putIfAbsent(remove.getRoomId(),remove);
                    //扣次数
                    reducePlayerTime(roomData);

                    syncRoomEventToRoomUser(eFlowerStudyRoomDataSyncType.gameStart.getValue(),roomData);
                }
            }
        }
    }

    /**
     * 扣除玩家参与次数
     */
    public void reducePlayerTime(CrossFlowerStudyExamRoomData roomData){
        Map<Long, CrossFlowerStudyUserBattleData> userBattleDataMap = roomData.getUserBattleDataMap();
        List<Long> needRemoveUser = new ArrayList<>();
        for (CrossFlowerStudyUserBattleData battleData : userBattleDataMap.values()){
            if (battleData.getUserId() <= AiMaxId){ //电脑人
                continue;
            }
            CrossFlowerStudyUserExamData userData = getUserData(battleData.getUserId());
            if (userData == null){
                needRemoveUser.add(battleData.getUserId());
                continue;
            }
            synchronized (userData){
                Map<Integer, Integer> todaySignUpCount = userData.getTodaySignUpCount();
                if (!todaySignUpCount.containsKey(roomData.getRoomType())){
                    todaySignUpCount.put(roomData.getRoomType(),0);
                    userData.setUpdateOption();
                }
                if (todaySignUpCount.get(roomData.getRoomType()) <= 0){
                    userData.setNowRoomId("");
                    needRemoveUser.add(battleData.getUserId());
                    continue;
                }
                todaySignUpCount.put(roomData.getRoomType(),todaySignUpCount.get(roomData.getRoomType())-1);
                userData.setUpdateOption();
            }
        }
        for (long userId : needRemoveUser){
            logger.error("flowerStudy reducePlayerTime userId:{} error ,quit from roomId={}",userId,roomData.getRoomId());
            userBattleDataMap.remove(userId);
        }
        roomData.setUpdateOption();
    }


    /**
     * 添加ai到上限
     */
    public void addAiToMax(CrossFlowerStudyExamRoomData roomData){
        FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
        if (config == null){
            return;
        }
        int examCanJoinNum = config.getExamRoomPlayerNum();
        synchronized (roomData){
            if (roomData.getUserBattleDataMap().size() >= examCanJoinNum){
                return;
            }
            int questionNum = roomData.getQuestionList().size();
            int needAddNum = examCanJoinNum - roomData.getUserBattleDataMap().size();
            //随机几个npcid
            List<Integer> npcIdList = RandomHelper.getDifferentRandomNum(AiMaxId, needAddNum);
            for (int i = 0;i < npcIdList.size();i++){
                CrossFlowerStudyExamNpcData npcData = getNpcData(npcIdList.get(i));
                if (npcData == null){
                    continue;
                }
                CrossFlowerStudyUserBattleData battleData = generateNewAiBattleInfo(npcData.getNpcId(),questionNum);
                roomData.getUserBattleDataMap().putIfAbsent(battleData.getUserId(),battleData);
            }
            syncRoomEventToRoomUser(eFlowerStudyRoomDataSyncType.playerJoin.getValue(), roomData);
        }
    }

    /**
     * 生成新ai
     */
    public CrossFlowerStudyUserBattleData generateNewAiBattleInfo(long id, int questionNum){
        CrossFlowerStudyUserBattleData battleData = new CrossFlowerStudyUserBattleData();
        battleData.setUserId(id);
        battleData.setNowState(1);
        battleData.setScoreThisExam(0);
        battleData.setTotalTimeThisExam(0);
        battleData.setReward("");
        battleData.setNowChooseList(new ArrayList<>());
        for (int i = 0; i < questionNum; i++) {
            battleData.getNowChooseList().add(1);
        }
        return battleData;
    }




    /**
     * 选择题目
     * @param userId
     * @param questionIndex
     * @param choose
     * @return
     */

    public FlowerStudyProto.FlowerStudyExamChooseResp.Builder chooseExamAnswer(long userId,int questionIndex,int choose){
        FlowerStudyProto.FlowerStudyExamChooseResp.Builder builder = FlowerStudyProto.FlowerStudyExamChooseResp.newBuilder();
        CrossFlowerStudyUserExamData userData = getUserData(userId);
        if (userData == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_USER_NO_INIT);
            return builder;
        }
        String nowRoomId = userData.getNowRoomId();
        if (StringUtils.isNullOrEmpty(nowRoomId)){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_STATE_ERROR);
            return builder;
        }
        if (endRoomDataMap.containsKey(nowRoomId)){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_OVER);
            return builder;
        }
        if (waitingRoomDataMap.containsKey(nowRoomId)){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_NO_START);
            return builder;
        }
        CrossFlowerStudyExamRoomData roomData = gamingRoomDataMap.get(nowRoomId);
        if (roomData == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_NO_EXIST);
            return builder;
        }
        if (roomData.getRoomState()!=1){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_STATE_ERROR);
            return builder;
        }

        if (roomData.getNowQuestionIndex() != questionIndex) {
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_ANSWER_LATE);
            return builder;
        }


        CrossFlowerStudyUserBattleData battleData = roomData.getUserBattleDataMap().get(userId);
        if (battleData == null) {
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_USER_NOT_IN_ROOM);
            return builder;
        }
        if (battleData.getNowState() == 3){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_OVER);
            return builder;
        }

        if (battleData.getNowChooseList().size() < roomData.getQuestionList().size()) {
            //如果有问题 修复一下
            for (int i = 0;i<(roomData.getQuestionList().size()-battleData.getNowChooseList().size());i++){
                battleData.getNowChooseList().add(1);
            }
        }

        int oldChoose = battleData.getNowChooseList().get(questionIndex);
        battleData.getNowChooseList().set(questionIndex, choose);

        if (oldChoose != choose) {
            syncChooseDataToRoomUser(userId,battleData,roomData);
        }

        builder.setRet(0);
        builder.setBattleData(parseUserBattleData(battleData));

        return builder;
    }

    /**
     * 同步选择给除了自己以外的所有人(除了ai)
     */
    public void syncChooseDataToRoomUser(long exceptUserId, CrossFlowerStudyUserBattleData battleData, CrossFlowerStudyExamRoomData roomData){
        FlowerStudyProto.FlowerStudyExamOtherChooseSync.Builder builder = FlowerStudyProto.FlowerStudyExamOtherChooseSync.newBuilder();
        builder.setBattleData(parseUserBattleData(battleData));

        for (CrossFlowerStudyUserBattleData otherUserBattleData : roomData.getUserBattleDataMap().values()) {
            if (otherUserBattleData.getUserId() == exceptUserId) {
                continue;
            }
            if (otherUserBattleData.getUserId() <= AiMaxId){    //假人
                continue;
            }
            CrossFlowerStudyUserExamData roomMateUserData = getUserData(otherUserBattleData.getUserId());
            if (roomMateUserData == null){
                continue;
            }
            YanQuMessage message = YanQuMessageUtils.buildMessage(ClientProtocol.U_FLOWER_STUDY_EXAM_OTHER_CHOOSE_SYNC, builder);
            MessageHelper.sendPacket(roomMateUserData.getServerId(),roomMateUserData.getUserId(),message);
        }
    }

    /**
     * 同步选择给玩家
     */
    public void syncChooseDataToUser(long syncToUser,int syncToServer,CrossFlowerStudyUserBattleData battleData){
        FlowerStudyProto.FlowerStudyExamOtherChooseSync.Builder builder = FlowerStudyProto.FlowerStudyExamOtherChooseSync.newBuilder();
        builder.setBattleData(parseUserBattleData(battleData));
        YanQuMessage message = YanQuMessageUtils.buildMessage(ClientProtocol.U_FLOWER_STUDY_EXAM_OTHER_CHOOSE_SYNC, builder);
        MessageHelper.sendPacket(syncToServer,syncToUser,message);
    }

    /**
     * 房间结算事件给房间单个玩家
     */
    public void syncRoomEndEventToOneUser(long syncToUser, int syncToServer, int syncType, CrossFlowerStudyExamRoomData roomData) {
        FlowerStudyProto.syncExamResultToGameServer.Builder syncBuilder = FlowerStudyProto.syncExamResultToGameServer.newBuilder();

        FlowerStudyProto.FlowerStudyExamRoomDataSync.Builder builder = FlowerStudyProto.FlowerStudyExamRoomDataSync.newBuilder();
        FlowerStudyProto.FlowerStudyExamRoomData.Builder roomDataToMsg = parseRoomDataToMsg(roomData);
        builder.setRoomData(roomDataToMsg);
        builder.setSyncType(syncType);
        builder.setReward(roomData.getUserBattleDataMap().get(syncToUser).getReward());

        syncBuilder.setRoomData(builder);
        syncBuilder.setActivityId(activityInfo.getActivityId());
        syncBuilder.setUserId(syncToUser);

        YanQuMessage message = YanQuMessageUtils.buildMessage(GameProtocol.S_FLOWER_STUDY_EXAM_EVENT_SYNC_RESULT_FROM_CROSS, syncBuilder);
        MessageHelper.sendPacket(syncToServer,0,message);
    }




    /**
     * 同步房间发生事件给房间内所有玩家
     */
    public void syncRoomEventToRoomUser(int syncType,CrossFlowerStudyExamRoomData roomData) {
        FlowerStudyProto.FlowerStudyExamRoomDataSync.Builder builder = FlowerStudyProto.FlowerStudyExamRoomDataSync.newBuilder();
        FlowerStudyProto.FlowerStudyExamRoomData.Builder roomDataToMsg = parseRoomDataToMsg(roomData);
        builder.setRoomData(roomDataToMsg);
        builder.setSyncType(syncType);


       synchronized (roomData){
           for (CrossFlowerStudyUserBattleData battleData : roomData.getUserBattleDataMap().values()) {
               if (battleData.getNowState() == 0){     //掉了 不管了
                   continue;
               }
               //只给活着的同步
               if (battleData.getNowState() == 3) {
                   continue;
               }

               long userId = battleData.getUserId();
               if (userId <= AiMaxId){    //假人
                   continue;
               }
               CrossFlowerStudyUserExamData userData = getUserData(userId);
               if (userData == null){
                   continue;
               }
               YanQuMessage message =YanQuMessageUtils.buildMessage(ClientProtocol.U_FLOWER_STUDY_EXAM_EVENT_SYNC, builder);
               MessageHelper.sendPacket(userData.getServerId(),userData.getUserId(),message);
           }
       }

    }

    /**
     * 获取当前房间详情
     * @param userId
     * @param serverId
     * @return
     */

    public FlowerStudyProto.FlowerStudyExamRoomNewestDataResp.Builder getRoomDetail (long userId,int serverId){
        FlowerStudyProto.FlowerStudyExamRoomNewestDataResp.Builder builder = FlowerStudyProto.FlowerStudyExamRoomNewestDataResp.newBuilder();
        CrossFlowerStudyUserExamData userData = getOrCreateUserData(userId, serverId);
        if (userData == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_USER_NO_INIT);
            return builder;
        }
        String nowRoomId = userData.getNowRoomId();

        if (StringUtils.isNullOrEmpty(nowRoomId)){
            builder.setRoomId("");
            builder.setRet(0);
            return builder;
        }

        CrossFlowerStudyExamRoomData roomData = null;

        if (waitingRoomDataMap.containsKey(nowRoomId)){
            roomData = waitingRoomDataMap.get(nowRoomId);
        }
        if (roomData == null && gamingRoomDataMap.containsKey(nowRoomId)){
            roomData = gamingRoomDataMap.get(nowRoomId);
        }
        builder.setRet(0);
        if (roomData == null){
            synchronized (userData){
                userData.setNowRoomId("");
            }

            return builder;
        }else {
            builder.setRoomId(nowRoomId);
            builder.setRoomData(parseRoomDataToMsg(roomData));
            return builder;
        }
    }

    public FlowerStudyProto.FlowerStudyExamSubmitAdvanceResp.Builder submitAdvance (long userId,int questionIndex){
        FlowerStudyProto.FlowerStudyExamSubmitAdvanceResp.Builder builder = FlowerStudyProto.FlowerStudyExamSubmitAdvanceResp.newBuilder();
        FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
        if (config == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_ACTIVITY_NO_OPEN);
            return builder;
        }
        CrossFlowerStudyUserExamData userData = getUserData(userId);
        if (userData == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_USER_NO_INIT);
            return builder;
        }
        String nowRoomId = userData.getNowRoomId();
        if (StringUtils.isNullOrEmpty(nowRoomId)){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_USER_NOT_IN_ROOM);
            return builder;
        }

        CrossFlowerStudyExamRoomData roomData = gamingRoomDataMap.get(nowRoomId);
        if (roomData == null){
            if (waitingRoomDataMap.containsKey(nowRoomId)){
                builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_NO_START);
                return builder;
            }else if (endRoomDataMap.containsKey(nowRoomId)){
                builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_OVER);
                return builder;
            }
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_NO_EXIST);
            return builder;
        }

        if (roomData.getRoomState() == 0){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_NO_START);
            return builder;
        }
        if (roomData.getRoomState() == 2){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_OVER);
            return builder;
        }

        int nowQuestionIndex = roomData.getNowQuestionIndex();
        if (nowQuestionIndex != questionIndex){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_ANSWER_LATE);
            return builder;
        }

        CrossFlowerStudyUserBattleData battleData = roomData.getUserBattleDataMap().get(userId);
        if (battleData == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_USER_NOT_IN_ROOM);
            return builder;
        }
        int oldState = battleData.getNowState();
        //如果已经死了 不给提前交卷
        if (oldState == 3){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_OVER);
            return builder;
        }


        //状态变更的情况下
        if (oldState != 2){
            battleData.setNowState(2);
            long cost = System.currentTimeMillis() / 1000 - roomData.getThisQuestionStartTime();
            if (cost < 1){
                cost = 1;
            }
            battleData.setTotalTimeThisExam(battleData.getTotalTimeThisExam() + cost);
            //同步给其他人
            syncChooseDataToRoomUser(userId,battleData,roomData);
        }
        builder.setRet(0);
        builder.setBattleData(parseUserBattleData(battleData));
        return builder;
    }

    public void loseConnect(long userId){
        CrossFlowerStudyUserExamData userData = getUserData(userId);
        String nowRoomId = userData.getNowRoomId();
        if (StringUtils.isNullOrEmpty(nowRoomId)){
            return;
        }
        CrossFlowerStudyExamRoomData roomData = null;
        if (waitingRoomDataMap.containsKey(nowRoomId)){
            roomData = waitingRoomDataMap.get(nowRoomId);
        }
        if (gamingRoomDataMap.containsKey(nowRoomId)){
            roomData = gamingRoomDataMap.get(nowRoomId);
        }
        if (endRoomDataMap.containsKey(nowRoomId)){
            roomData = endRoomDataMap.get(nowRoomId);
        }

        if (roomData.getRoomState() == 2){
            //房间已经结束，直接退出
            return;
        }

        if (roomData.getRoomState() == 0){
            //房间还没开始，直接退出
            cancelMatching(userId);
            return;
        }
        if (roomData.getRoomState() == 1){
            synchronized (roomData){
                CrossFlowerStudyUserBattleData battleData = roomData.getUserBattleDataMap().get(userId);
                if (battleData != null){
                    battleData.setNowState(0);
                }
            }
        }


    }

    public FlowerStudyProto.FlowerStudyExamQuitRoomResp.Builder quitRoom(long userId){
        FlowerStudyProto.FlowerStudyExamQuitRoomResp.Builder builder = FlowerStudyProto.FlowerStudyExamQuitRoomResp.newBuilder();
        CrossFlowerStudyUserExamData userData = getUserData(userId);
        if (userData == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_USER_NO_INIT);
            return builder;
        }
        String nowRoomId = userData.getNowRoomId();
        CrossFlowerStudyExamRoomData roomData = null;
        if (waitingRoomDataMap.containsKey(nowRoomId)){
            roomData = waitingRoomDataMap.get(nowRoomId);

        }
        if (gamingRoomDataMap.containsKey(nowRoomId)){
            roomData = gamingRoomDataMap.get(nowRoomId);
        }
        if (endRoomDataMap.containsKey(nowRoomId)){
            roomData = endRoomDataMap.get(nowRoomId);
        }
        if (roomData == null){
            synchronized (userData){
                userData.setNowRoomId("");
            }
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_NO_EXIST);
            return builder;
        }
        //锁住房间
        synchronized (roomData){
            if (roomData.getRoomState() == 0 || roomData.getRoomState() == 2){
                waitingRoomDataMap.get(nowRoomId).getUserBattleDataMap().remove(userId);
                synchronized (userData){
                    userData.setNowRoomId("");
                }
                builder.setRet(0);
                return builder;
            }
            //正在游戏的房间
            if (roomData.getRoomState() == 1){
                CrossFlowerStudyUserBattleData battleData = roomData.getUserBattleDataMap().get(userId);
                if (battleData == null){
                    synchronized (userData){
                        userData.setNowRoomId("");
                    }
                    builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_USER_NOT_IN_ROOM);
                    return builder;
                }

                if (battleData.getNowState() == 3){
                    gamingRoomDataMap.get(nowRoomId).getUserBattleDataMap().remove(userId);
                    synchronized (userData){
                        userData.setNowRoomId("");
                    }
                    builder.setRet(0);
                    return builder;
                }
                battleData.setNowState(3);  //死翘翘了
                CrossFlowerStudyUserExamData userExamData = userExamDataMap.get(battleData.getUserId());
                if (userExamData == null){
                    logger.info("花生书房 活动id{},玩家信息不存在 userId:{},房间id:{}",activityInfo.getActivityId(),battleData.getUserId(),roomData.getRoomId());
                }
                //结算
                dealGameOver(battleData,roomData);
                syncRoomEventToRoomUser(eFlowerStudyRoomDataSyncType.playerLeave.getValue(),roomData);
                builder.setRet(0);
                builder.setRoomData(parseRoomDataToMsg(roomData));
                builder.setReward(battleData.getReward());
                return builder;
            }else {
                synchronized (userData){
                    userData.setNowRoomId("");
                }
                builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_USER_NOT_IN_ROOM);
                return builder;
            }

        }

    }


    public FlowerStudyProto.FlowerStudyExamMatchingCancelResp.Builder cancelMatching (long userId){
        FlowerStudyProto.FlowerStudyExamMatchingCancelResp.Builder builder = FlowerStudyProto.FlowerStudyExamMatchingCancelResp.newBuilder();
        CrossFlowerStudyUserExamData userData = getUserData(userId);
        if (StringUtils.isNullOrEmpty(userData.getNowRoomId())){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_USER_NOT_IN_ROOM);
            return builder;
        }
        if (gamingRoomDataMap.containsKey(userData.getNowRoomId())){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_NO_CANCEL);
            return builder;
        }
        if (endRoomDataMap.containsKey(userData.getNowRoomId())){
            synchronized (userData){
                userData.setNowRoomId("");
            }
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_OVER);
            return builder;
        }

        CrossFlowerStudyExamRoomData roomData = waitingRoomDataMap.get(userData.getNowRoomId());
        if (roomData == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_NO_EXIST);
            synchronized (userData){
                userData.setNowRoomId("");
            }
            return builder;
        }

        synchronized (roomData){
            if (roomData.getRoomState() == 1){
                builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_NO_CANCEL);
                return builder;
            }
            roomData.getUserBattleDataMap().remove(userId);
        }
        synchronized (userData){
            userData.setNowRoomId("");
        }
        builder.setRet(0);
        return builder;
    }

    public FlowerStudyProto.FlowerStudyExamMatchingStartResp.Builder startMatching(int type, long userId, int serverId){
        FlowerStudyProto.FlowerStudyExamMatchingStartResp.Builder builder = FlowerStudyProto.FlowerStudyExamMatchingStartResp.newBuilder();

        FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
        if (config == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_ACTIVITY_NO_OPEN);
            return builder;
        }

        int roomPlayerNum = config.getExamRoomPlayerNum();

        CrossFlowerStudyUserExamData userData = getOrCreateUserData(userId, serverId);
        if (userData == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_USER_NO_INIT);
            return builder;
        }

        if (!userData.getNowRoomId().equals("")){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_HAS_JOIN_ROOM);
            return builder;
        }
        updateQualification(userData);
        if (userData.getHasQualificationExamSession() < type){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_PALACE_EXAM_NO_QUALIFICATION);
            return builder;
        }

        int nowOpenTest = getNowOpenTest();
        if (nowOpenTest <= 0 ){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_EXAM_SESSION_NO_OPEN);
            return builder;
        }

        CrossFlowerStudyExamSessionData sessionData = sessionDataMap.get(nowOpenTest);

        if (sessionData == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_EXAM_SESSION_NO_OPEN);
            return builder;
        }

        if (sessionData.getRoomType() != type){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_EXAM_SESSION_NO_OPEN);
            return builder;
        }

        if (!userData.getTodaySignUpCount().containsKey(type)){
            userData.getTodaySignUpCount().put(type,0);
            userData.setUpdateOption();
        }
        if (userData.getTodaySignUpCount().get(type)<=0){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_PALACE_EXAM_NO_TIMES);
            return builder;
        }



        synchronized (waitingRoomDataMap){

            CrossFlowerStudyExamRoomData canJoinRoomData = null;
            for (CrossFlowerStudyExamRoomData roomData:waitingRoomDataMap.values()) {
                if (roomData.getRoomState() != 0){
                    continue;
                }
                if (roomData.getUserBattleDataMap().size()>=roomPlayerNum){
                    continue;
                }
                if (roomData.getRoomType() != type){
                    continue;
                }
                if (roomData.getUserBattleDataMap().containsKey(userId)){
                    builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_HAS_JOIN_ROOM);
                    return builder;
                }
                canJoinRoomData = roomData;
                break;
            }
            if (canJoinRoomData == null){   //没有空房间 创建一个
                AtomicInteger atomicRoomId = sessionData.getAtomicRoomId();
                int maxRoomId = atomicRoomId.incrementAndGet();
                String roomId= type+"_"+sessionData.getSessionId()+"_"+maxRoomId;
                while (waitingRoomDataMap.containsKey(roomId)||gamingRoomDataMap.containsKey(roomId)||endRoomDataMap.containsKey(roomId)){
                    maxRoomId = atomicRoomId.incrementAndGet();
                    roomId= type+"_"+sessionData.getSessionId()+"_"+maxRoomId;
                }
                CrossFlowerStudyExamRoomData examRoom = createExamRoom(type,roomId);
                if (examRoom == null){
                    builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_CREATE_ROOM_ERROR);
                    return builder;
                }
                if (maxRoomId >sessionData.getRoomId()){
                    sessionData.setRoomId(maxRoomId);
                }
                canJoinRoomData = examRoom;
                waitingRoomDataMap.put(examRoom.getRoomId(),examRoom);
            }
            synchronized (canJoinRoomData){
               int ret = joinRoom(userId, canJoinRoomData);
               if (ret!=0){
                   builder.setRet(ret);
                   return builder;
               }
            }
            synchronized (userData){
                userData.setNowRoomId(canJoinRoomData.getRoomId());
            }
            builder.setRet(0);
            builder.setRoomData(parseRoomDataToMsg(canJoinRoomData));
            syncRoomEventToRoomUser(eFlowerStudyRoomDataSyncType.playerJoin.getValue(),canJoinRoomData);

        }
        return builder;

    }

    /**
     * 加入房间
     * @param userId
     * @param roomData
     * @return
     */

    private int joinRoom(long userId,CrossFlowerStudyExamRoomData roomData){
        if (roomData.getRoomState() != 0){
            return GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_STATE_ERROR;
        }
        int maxPlayerInRoomByType = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId()).getExamRoomPlayerNum();
        if (maxPlayerInRoomByType <= 0 || roomData.getUserBattleDataMap().size() >= maxPlayerInRoomByType){
            return GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_ROOM_FULL;
        }

        CrossFlowerStudyUserBattleData battleData = new CrossFlowerStudyUserBattleData();
        battleData.setUserId(userId);
        battleData.setNowState(1);
        battleData.setScoreThisExam(0);
        battleData.setTotalTimeThisExam(0);
        battleData.setReward("");
        battleData.setNowChooseList(new ArrayList<>());
        for (int i :roomData.getQuestionList()){
            battleData.getNowChooseList().add(1);
        }
        roomData.getUserBattleDataMap().put(userId,battleData);
        roomData.setUpdateOption();
        return 0;

    }

    /**
     * 创建房间
     * @param type
     * @return
     */

    private CrossFlowerStudyExamRoomData createExamRoom(int type,String roomId){
        CrossFlowerStudyExamRoomData roomData = new CrossFlowerStudyExamRoomData();
        roomData.setActivityId(activityInfo.getActivityId());
        roomData.setRoomId(roomId);
        roomData.setRoomType(type);
        roomData.setRoomState(0);
        roomData.setUserBattleDataMap(new ConcurrentHashMap<>());
        List<Integer> randomQuestionList = CrossFlowerStudyConfigMgr.getRandomQuestionList(activityInfo.getActivityId(), type);
        if (randomQuestionList == null){
            return null;
        }
        FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
        if (config == null){
            return null;
        }
        int joinAiTime = config.getJoinAiTime();

        roomData.setQuestionList(randomQuestionList);
        roomData.setNowQuestionIndex(-1);
        long now = System.currentTimeMillis();
        roomData.setMatchEndTime(now + DateHelper.SECOND_MILLIONS * joinAiTime);
        roomData.setThisQuestionStartTime(now + DateHelper.SECOND_MILLIONS * (joinAiTime+2));
        roomData.setEndTime(0);
        roomData.setAiLastMoveTime(0);
        roomData.setInsertOption();

        return roomData;
    }

    /**
     * 房间数据转化为消息
     * @param roomData
     * @return
     */

    public FlowerStudyProto.FlowerStudyExamRoomData.Builder parseRoomDataToMsg(CrossFlowerStudyExamRoomData roomData){
        FlowerStudyProto.FlowerStudyExamRoomData.Builder builder = FlowerStudyProto.FlowerStudyExamRoomData.newBuilder();
        builder.setRoomId(roomData.getRoomId());
        builder.setRoomType(roomData.getRoomType());
        builder.setRoomStatus(roomData.getRoomState());
        for (CrossFlowerStudyUserBattleData battleData:roomData.getUserBattleDataMap().values()) {
            //对战数据
            FlowerStudyProto.FlowerStudyExamUserBattleData.Builder battleDataBuilder = parseUserBattleData(battleData);
            builder.addUserBattleData(battleDataBuilder);

            //玩家数据
            FlowerStudyProto.FlowerStudyUserBaseInfoData.Builder dataBuilder = FlowerStudyProto.FlowerStudyUserBaseInfoData.newBuilder();
            if (battleData.getUserId() <= AiMaxId){
                CrossFlowerStudyExamNpcData npcData = getNpcData(battleData.getUserId());
                if (npcData == null){
                    dataBuilder.setUserId(battleData.getUserId());
                    dataBuilder.setServerId(getRandomServerId());
                    dataBuilder.setName(getRandomName());
                    dataBuilder.setDecoration(String.valueOf(randomGetNpcHeadId()));
                    dataBuilder.setVipExp(random.nextInt(1000));
                    dataBuilder.setVipDisplay(0);
                }else {
                    dataBuilder.setUserId(npcData.getNpcId());
                    dataBuilder.setServerId(npcData.getServerId());
                    dataBuilder.setName(npcData.getNpcName());
                    dataBuilder.setDecoration(npcData.getDecoration());
                    dataBuilder.setVipExp(npcData.getVipLevel());
                    dataBuilder.setVipDisplay(0);
                }
            }else {
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(battleData.getUserId());
                if (userBaseInfo == null){
                    dataBuilder.setUserId(battleData.getUserId());
                    dataBuilder.setServerId(getRandomServerId());
                    dataBuilder.setName(getRandomName());
                    dataBuilder.setDecoration(String.valueOf(randomGetNpcHeadId()));
                    dataBuilder.setVipExp(random.nextInt(1000));
                    dataBuilder.setVipDisplay(0);
                }else {
                    dataBuilder.setUserId(battleData.getUserId());
                    dataBuilder.setServerId(userBaseInfo.getServerId());
                    dataBuilder.setName(userBaseInfo.getNickName());
                    dataBuilder.setDecoration(userBaseInfo.getDecoration());
                    dataBuilder.setVipExp(userBaseInfo.getVipExp());
                    dataBuilder.setVipDisplay(userBaseInfo.getHideVipAndAddress());
                }
            }
            builder.addUserBaseInfo(dataBuilder);
        }
        builder.addAllQuestion(roomData.getQuestionList());
        builder.setNowQuestionIndex(roomData.getNowQuestionIndex());
        builder.setMatchEndTime(roomData.getMatchEndTime());
        builder.setStartTime(roomData.getThisQuestionStartTime());
        builder.setEndTime(roomData.getEndTime());
        return builder;
    }

    public  FlowerStudyProto.FlowerStudyExamUserBattleData.Builder parseUserBattleData(CrossFlowerStudyUserBattleData battleData){
        FlowerStudyProto.FlowerStudyExamUserBattleData.Builder builder = FlowerStudyProto.FlowerStudyExamUserBattleData.newBuilder();
        builder.setUserId(battleData.getUserId());
        builder.setNowState(battleData.getNowState());
        builder.setScoreThisExam(battleData.getScoreThisExam());
        builder.addAllChoose(battleData.getNowChooseList());
        builder.setTotalUseTime(battleData.getTotalTimeThisExam());
        return builder;
    }



    public CrossFlowerStudyActivity(ActivityInfo activityInfo) {
        this.activityInfo = activityInfo;
    }

    /**
     * 获取玩家数据
     */
    public CrossFlowerStudyUserExamData getUserData(long userId){
        return userExamDataMap.get(userId);
    }

    /**
     * 获取或初始化用户数据
     * @param userId
     * @param serverId
     * @return
     */

    public CrossFlowerStudyUserExamData getOrCreateUserData(long userId,int serverId){
        if (!userExamDataMap.containsKey(userId)){
            synchronized (userExamDataMap){
                if (!userExamDataMap.containsKey(userId)){
                    CrossFlowerStudyUserExamData userExamData = new CrossFlowerStudyUserExamData();
                    userExamData.setUserId(userId);
                    userExamData.setServerId(serverId);
                    userExamData.setActivityId(activityInfo.getActivityId());
                    userExamData.setLocalExamScore(0);
                    userExamData.setProvinceExamScore(0);
                    userExamData.setPalaceExamScore(0);
                    userExamData.setLocalExamTime(0);
                    userExamData.setProvinceExamTime(0);
                    userExamData.setPalaceExamTime(0);
                    userExamData.setHasQualificationExamSession(1);
                    Map<Integer, Integer> initJoinTimeMap = CrossFlowerStudyConfigMgr.getInitJoinTimeMap(activityInfo.getActivityId());
                    if (initJoinTimeMap == null || initJoinTimeMap.isEmpty()){
                        return null;
                    }
                    userExamData.setTodaySignUpCount(initJoinTimeMap);

                    userExamData.setNowRoomId("");
                    userExamData.setInsertOption();

                    userExamDataMap.put(userId,userExamData);
                }
            }

        }
        return userExamDataMap.get(userId);
    }

    /**
     * 获取跨服数据
     */
    public FlowerStudyProto.getUserCrossDataToServerResp.Builder getCrossUserData(long userId, int serverId){
        FlowerStudyProto.getUserCrossDataToServerResp.Builder builder = FlowerStudyProto.getUserCrossDataToServerResp.newBuilder();
        CrossFlowerStudyUserExamData userData = getOrCreateUserData(userId, serverId);
        if (userData == null){
            builder.setRet(GameErrorCode.E_FLOWER_STUDY_CROSS_ACTIVITY_USER_NO_INIT);
            return builder;
        }
        //检测是否有资格
        updateQualification(userData);
        builder.setRet(0);
        builder.setCrossUserData(parseUserCrossDataToMsg(userData));
        return builder;
    }

    /**
     * 更新玩家资格
     */

    public void updateQualification(CrossFlowerStudyUserExamData userData) {
        FlowerStudyConfig config = CrossFlowerStudyConfigMgr.getConfig(activityInfo.getActivityId());
        if (config == null) {
            return;
        }
        if (userData.getHasQualificationExamSession() == 3) {
            return;
        }
        Date date = new Date();
        if (!checkCanGetScore(2) && date.after(config.getProvincialExamEndDate())) {
            int myRank = ActivityRankMgr.getNewCrossActivityRank(activityInfo.getActivityId(), eGamePlayerEventType.FlowerStudyScoreProvinceRankCondition.getValue(), userData.getServerId(), userData.getUserId());
            if (myRank <= config.getPalaceExamNeedRanking() && myRank > 0) {
                userData.setHasQualificationExamSession(3);
            }
            return;
        }
        if (!checkCanGetScore(1) && date.after(config.getLocalExamEndDate())) {
            int myRank = ActivityRankMgr.getNewCrossActivityRank(activityInfo.getActivityId(), eGamePlayerEventType.FlowerStudyScoreLocalRankCondition.getValue(), userData.getServerId(), userData.getUserId());
            if (myRank <= config.getProvincialExamNeedRanking() && myRank > 0) {
                userData.setHasQualificationExamSession(2);
            }
            return;
        }
    }


    /**
     * 解析跨服玩家数据变为消息
     */
    public FlowerStudyProto.CrossFlowerStudyUserData.Builder parseUserCrossDataToMsg(CrossFlowerStudyUserExamData userData){
        FlowerStudyProto.CrossFlowerStudyUserData.Builder builder = FlowerStudyProto.CrossFlowerStudyUserData.newBuilder();
        builder.setActivityId(userData.getActivityId());
        builder.setRoomId(userData.getNowRoomId());
        builder.setLocalScore(userData.getLocalExamScore());
        builder.setPalaceScore(userData.getPalaceExamScore());
        builder.setProvinceScore(userData.getProvinceExamScore());
        builder.setHasSignUpLevel(userData.getHasQualificationExamSession());
        for (Map.Entry<Integer,Integer> entry:userData.getTodaySignUpCount().entrySet()){
            FlowerStudyProto.FlowerStudyUserJoinExamTime.Builder timeBuilder = FlowerStudyProto.FlowerStudyUserJoinExamTime.newBuilder();
            timeBuilder.setType(entry.getKey());
            timeBuilder.setTime(entry.getValue());
            builder.addJoinTime(timeBuilder);
        }
        builder.setLocalTime(userData.getLocalExamTime());
        builder.setProvinceTime(userData.getProvinceExamTime());
        builder.setPalaceTime(userData.getPalaceExamTime());
        return builder;
    }

    public CrossFlowerStudyExamNpcData getNpcData(long npcId){
        if (!npcDataMap.containsKey(npcId)){
            CrossFlowerStudyExamNpcData npcData = generateNpcData(npcId);
            npcDataMap.put(npcId,npcData);
        }
        return npcDataMap.get(npcId);
    }

    public CrossFlowerStudyExamNpcData generateNpcData(long npcId){
        CrossFlowerStudyExamNpcData npcData = new CrossFlowerStudyExamNpcData();
        npcData.setNpcId(npcId);
        npcData.setDecoration(String.valueOf(randomGetNpcHeadId()));
        npcData.setNpcName(getRandomName());
        npcData.setServerId(getRandomServerId());
        if(random.nextInt(3)==1){
            npcData.setVipLevel(random.nextInt(500));
        }else {
            npcData.setVipLevel(0);
        }

        return npcData;
    }

    public String getRandomName(){
        if (languageList.isEmpty()){
            return NameMgr.getRandomNameWithOutCheck(eSexType.MALE, LanguageType.LANGUAGE_DEFAULT);
        }
        if (languageList.size() == 1){
            return NameMgr.getRandomNameWithOutCheck(eSexType.MALE, languageList.get(0));
        }
        int index = random.nextInt(languageList.size());
        return NameMgr.getRandomNameWithOutCheck(eSexType.MALE, languageList.get(index));
    }

    public long getRandomServerId(){
        List<Long> serverIdList = activityInfo.getServerIdList();
        int index = random.nextInt(serverIdList.size());
        return serverIdList.get(index);
    }

    private int randomGetNpcHeadId() {
        return CrossFlowerStudyConfigMgr.getRandomAiIcon(activityInfo.getActivityId());
    }

    /**
     * 排行榜更新
     * @param examData
     */

    public void syncRankToGame(CrossFlowerStudyUserExamData examData){
        FlowerStudyProto.syncStudyExamRankToGameReq.Builder builder = FlowerStudyProto.syncStudyExamRankToGameReq.newBuilder();
        FlowerStudyProto.CrossFlowerStudyUserData.Builder userBuilder = parseUserCrossDataToMsg(examData);
        builder.setData(userBuilder);
        builder.setUserId(examData.getUserId());
        YanQuMessage yanQuMessage = YanQuMessageUtils.buildMessage(GameProtocol.S_FLOWER_STUDY_CROSS_SEND_RANK_TO_GAME, builder);
        MessageHelper.sendPacket(examData.getServerId(),0,yanQuMessage);

    }

    /**
     * 更新语言表
     */
    public void updateLanguage(String language){
        if (StringUtils.isNullOrEmpty(language)){
            return;
        }
        if (languageList.contains(language)){
            return;
        }
        languageList.add(language);
    }


}
